メッセージ・フローグラフの例

この例では、すべての x = 1 to 10 の合計 x*x + x*x*x を計算します。この例のレイアウトは、下図のようになります。

./message_flow_graph.jpg

単純なメッセージ・フローグラフ

それぞれの値は、broadcast_node<int> input を介して入力されます。このノードは、値を squarercuber (x*x および x*x*x を計算) にブロードキャストします。これらのノードの出力は、join のポートの 1 つに送られます。join_node<std::tuple<int,int>> join で両方の値を含むタプルが作成され、summer (両方の値を合計に追加) に送られます。squarercuber はどちらも無制限に並列化できます。つまり、複数の値を同時に処理できます。最後の summer (共有の合計を更新) は、共有値をロックしなくてもいいように、一度に 1 つの受け取ったタプルのみ処理します。

#include <cstdio> 
#include 
"oneapi/tbb/flow_graph.h" 

using namespace oneapi::tbb::flow; 

struct square { 
    int operator()(int v) { return v*v; } 
}; 

struct cube { 
    int operator()(int v) { return v*v*v; } 
}; 

class sum { 
    int &my_sum; 
public: 
    sum( int &s ) : my_sum(s) {} 
    int operator()( std::tuple<int, int> v ) { 
        my_sum += get<0>(v) + get<1>(v); 
        return my_sum; 
    } 
}; 

int main() { 
    int result = 0; 

    graph g; 
    broadcast_node<int> input(g); 
    function_node<int,int> squarer( g, unlimited, square() ); 
    function_node<int,int> cuber( g, unlimited, cube() ); 
    join_node<std::tuple<int,int>, queueing> join( g ); 
    function_node<std::tuple<int,int>,int> 
        summer( g, serial, sum(result) ); 

    make_edge( input, squarer ); 
    make_edge( input, cuber ); make_edge( squarer, get<0>( join.input_ports() ) ); 
    make_edge( cuber, get<1>( join.input_ports() ) ); 
    make_edge( join, summer ); 

    for (int i = 1; i <= 10; ++i) 
        input.try_put(i); 
    g.wait_for_all(); 

    printf("Final result is %d\n", result); 
    return 0; 
}

上記のサンプルコードでは、squarecubesum クラスは 3 つのユーザー定義操作を定義しています。各クラスは function_node の作成に使用されます。

main 関数で、フローグラフがセットアップされ、値 1-10 が input ノードに送られます。この例のノードはすべて int タイプの値を渡します。この例で使用されているノードはすべてテンプレート・クラスであるため、ポインターとオブジェクトを含む、コピー構築をサポートするすべてのタイプで使用できます。